using System;
using System.Collections.Generic;
using System.Text;
using System.Reflection;
using MbUnit;
using MbUnit.Framework;
using MbUnit.Core.Framework;
using MbUnit.Core.Exceptions;

namespace TestAssistance
{
    public static class Assertor
    {
        public static void ReflectiveEquals(Object expected, Object actual)
        {
            if (expected.GetType() != actual.GetType())
                throw new AssertionException("The types are not the same, they can not be the same.");
            foreach (PropertyInfo Property in expected.GetType().GetProperties())
            {
                if (Property.GetGetMethod().IsPublic)
                {
                    if (Property.GetGetMethod().GetParameters() == null || Property.GetGetMethod().GetParameters().Length == 0)
                    {
                        Object ExpectedValue = Property.GetValue(expected, null);
                        Object ActualValue = Property.GetValue(actual, null);
                        Boolean ImplementsEquals = false;
                        foreach (MethodInfo EqualsMethod in Property.PropertyType.GetMethods(BindingFlags.Public | BindingFlags.Instance))
                        {
                            if (EqualsMethod.Name == "Equals" && EqualsMethod.GetParameters() != null && EqualsMethod.GetParameters().Length == 1 && EqualsMethod.GetParameters()[0].GetType() == typeof(Object))
                            {
                                if (EqualsMethod.DeclaringType != typeof(Object))
                                {
                                    ImplementsEquals = true;
                                }
                                break;
                            }
                        }
                        if (!ImplementsEquals)
                        {
                            Assertor.ReflectiveEquals(ExpectedValue, ActualValue);
                        }
                        else
                        {
                            if (ExpectedValue != ActualValue)
                            {
                                throw new AssertionException(string.Format("Property {0}: expected value {1} does not equal {2}", Property.Name, ExpectedValue.ToString(), ActualValue.ToString()));
                            }
                            Assert.IncrementAssertCount();
                        }
                    }
                }
            }
        }

    }
}
